package com.cloud.pole.shop.service.order.impl;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.ace.cache.api.CacheAPI;
import com.cloud.pole.api.param.PicklistApi;
import com.cloud.pole.api.user.UserAccountApi;
import com.cloud.pole.api.user.UserAuthorizedWxApi;
import com.cloud.pole.common.constant.CommonConstants;
import com.cloud.pole.common.exception.BaseException;
import com.cloud.pole.common.msg.ApiRestResponse;
import com.cloud.pole.common.util.jwt.IJWTInfo;
import com.cloud.pole.common.util.jwt.JwtTokenUtil;
import com.cloud.pole.common.util.security.MD5SignUtils;
import com.cloud.pole.common.util.security.MD5Utils;
import com.cloud.pole.feign.IParamPickListService;
import com.cloud.pole.feign.IPayService;
import com.cloud.pole.feign.IUserAccountService;
import com.cloud.pole.feign.IUserService;
import com.cloud.pole.feign.IWeiXinService;
import com.cloud.pole.shop.biz.goods.ShopGoodsBiz;
import com.cloud.pole.shop.biz.goods.ShopGoodsSpecBiz;
import com.cloud.pole.shop.biz.order.ShopOrderBiz;
import com.cloud.pole.shop.biz.order.ShopOrderItemsBiz;
import com.cloud.pole.shop.biz.order.ShopOrderPayBiz;
import com.cloud.pole.shop.biz.shops.ShopShopsPayMethodBiz;
import com.cloud.pole.shop.biz.shops.ShopShopsPayTypeBiz;
import com.cloud.pole.shop.biz.shops.ShopShopsPayTypeStageNumBiz;
import com.cloud.pole.shop.config.BusiConfiguration;
import com.cloud.pole.shop.constant.ShopCommonConstant;
import com.cloud.pole.shop.model.entity.goods.ShopGoods;
import com.cloud.pole.shop.model.entity.goods.ShopGoodsSpec;
import com.cloud.pole.shop.model.entity.order.ShopOrder;
import com.cloud.pole.shop.model.entity.order.ShopOrderItems;
import com.cloud.pole.shop.model.entity.order.ShopOrderPay;
import com.cloud.pole.shop.model.entity.shops.ShopShopsPayMethod;
import com.cloud.pole.shop.model.entity.shops.ShopShopsPayType;
import com.cloud.pole.shop.model.entity.shops.ShopShopsPayTypeStageNum;
import com.cloud.pole.shop.model.vo.order.ShopOrderToPayVo;
import com.cloud.pole.shop.rabbit.RabbitSender;
import com.cloud.pole.shop.service.goods.GoodsService;
import com.cloud.pole.shop.service.order.OrderPayService;

import lombok.extern.slf4j.Slf4j;

/*
*2019年3月4日
*cloud-shop
*author:frank-chen
*/
@Service
@Slf4j
public class OrderPayServiceImpl implements OrderPayService {

	@Autowired 
	private ShopOrderBiz shopOrderBiz;
	@Autowired 
	private ShopOrderItemsBiz shopOrderItemsBiz;
	@Autowired 
	private ShopGoodsBiz shopGoodsBiz;
	@Autowired 
	private ShopGoodsSpecBiz shopGoodsSpecBiz;
	@Autowired 
	private GoodsService goodsService;
	@Autowired
	private IParamPickListService paramPickListService;
	@Autowired
	private IUserAccountService userAccountService;
	@Autowired
	private ShopOrderPayBiz shopOrderPayBiz;
	@Autowired
	private IUserService userService;
	@Autowired
	private IWeiXinService weiXinService;
	@Autowired
	private BusiConfiguration busiConfiguration;
	@Autowired 
	private ShopShopsPayTypeBiz shopShopsPayTypeBiz;
	@Autowired 
	private ShopShopsPayMethodBiz shopShopsPayMethodBiz;
	@Autowired 
	private ShopShopsPayTypeStageNumBiz shopShopsPayTypeStageNumBiz;
	@Autowired
	private IPayService payService;
	@Autowired
    private CacheAPI cacheAPI;
	@Autowired
	private RabbitSender rabbitSender;

	@Override
	public ShopOrderToPayVo getToOrderPay(String token, String orderIds) throws Exception {
		IJWTInfo jwtInfo = JwtTokenUtil.getInfoFromToken(token);
		//根据订单查询
		orderIds = orderIds.substring(1, orderIds.length() - 1).trim();
		String[] orderArray = orderIds.split("\\|\\|");
		//总金额
		long totalPrice = 0; 
		//总重量
		long totalFreight = 0;
		//总优惠
		long totalPromotion = 0;
		Integer shopId = 0;
		for(String orderId : orderArray) {
			//查询订单信息
			ShopOrder shopOrder = shopOrderBiz.selectByPrimaryKey(orderId);
			shopId = shopOrder.getShopId();
			if(shopOrder == null || shopOrder.getUserId().longValue() != Long.parseLong(jwtInfo.getId())) {
				throw new BaseException(CommonConstants.STATUS_ERROR_CODE, "订单id错误");
			}
			if(shopOrder.getOrderStatus().intValue() != ShopOrder.ORDER_STATUS_DEFAULT && 
			   shopOrder.getOrderStatus().intValue() != ShopOrder.ORDER_STATUS_COMFIRM
			   ) {
				throw new BaseException(CommonConstants.STATUS_ERROR_CODE, "订单状态错误");
			}
			//查询订单产品列表
			List<ShopOrderItems> shopOrderItemsList = shopOrderItemsBiz.selectOrderItemsList(orderId);
			if(shopOrderItemsList == null) {
				throw new BaseException(CommonConstants.STATUS_ERROR_CODE, "订单明细错误");
			}
			//验证订单规格
			for(ShopOrderItems shopOrderItems : shopOrderItemsList) {
			    //检测specId、goodId是否有效
				ShopGoods shopGoods = shopGoodsBiz.selectByPrimaryKey(shopOrderItems.getGoodsId());
				goodsService.checkShoppingGoods(shopGoods);
				ShopGoodsSpec shopGoodsSpec = shopGoodsSpecBiz.selectById(shopOrderItems.getGoodsSpecId());
				goodsService.checkGoodsSpec(shopGoodsSpec);

				//检测库存是否足够
				if(shopGoods.getStockStatus() == -1) {
					throw new BaseException(CommonConstants.STATUS_ERROR_CODE, "库存不够");
				}
				if(shopGoodsSpec.getStockQuantity().intValue() < shopOrderItems.getProductNum().intValue() ) {
					throw new BaseException(CommonConstants.STATUS_ERROR_CODE, "库存不够");
				}
			}
			totalPrice += shopOrder.getProductAmount();
			totalFreight += shopOrder.getFreightAmount();
		}
		ShopOrderToPayVo shopOrderToPayVo = new ShopOrderToPayVo();
		//查询付款方式
		List<ShopShopsPayMethod> payMethodList = shopShopsPayMethodBiz.selectListByShopId(shopId);
		if(!payMethodList.isEmpty()){
			ShopShopsPayMethod method = payMethodList.get(0);
			shopOrderToPayVo.setPayMethod(method);
			//查询支付方式
			Map<String, Object> map = new HashMap<String, Object>();
			map.put("shopId", shopId);
			map.put("payMethodId", method.getPayMethodId());
			List<ShopShopsPayType> payTypeList = shopShopsPayTypeBiz.selectListByMap(map);
			if(!payTypeList.isEmpty()){
				shopOrderToPayVo.setPayTypeList(payTypeList);
				if(method.getPayMethod().equals(10)){
					map.put("payTypeId", payTypeList.get(0).getPayTypeId());
					List<ShopShopsPayTypeStageNum> stageNumList = shopShopsPayTypeStageNumBiz.selectListByMap(map);
					shopOrderToPayVo.setStageNumList(stageNumList);
				}
			}
		}
		//查询账户余额
		ApiRestResponse<List<UserAccountApi>> userAccountResponse = userAccountService.getAccountList(token);
		if(userAccountResponse.getStatus() != CommonConstants.STATUS_OK_CODE) {
			throw new BaseException(userAccountResponse.getStatus(), userAccountResponse.getMessage());
		}
		List<UserAccountApi> userAccountList = userAccountResponse.getData();
		
		shopOrderToPayVo.setProductAmount(Long.valueOf(totalPrice));
		shopOrderToPayVo.setUserAccountList(userAccountList);
		
		ShopOrderPay shopOrderPay = shopOrderPayBiz.selectByOrderSn(orderIds);
		if(shopOrderPay != null) {
			shopOrderToPayVo.setPayId(shopOrderPay.getPayId());
		}
		
		String recommandMarketCode = cacheAPI.get("recommandMarketCode-" + token);
		shopOrderToPayVo.setRecommandMarketCode(recommandMarketCode);
		return shopOrderToPayVo;
	}

	/**
	 * 订单支付
	 */
	@Override
	public String doOrderPay(String token, Long payId, Integer payType, String payPwd, String openId, 
			Integer payMethod, Integer stageNumId, Integer stageNum) throws Exception {
		// TODO Auto-generated method stub
		IJWTInfo jwtInfo = JwtTokenUtil.getInfoFromToken(token);
		ShopOrderPay searchPay = shopOrderPayBiz.selectByPrimaryKey(payId);
		if(searchPay == null || Long.parseLong(jwtInfo.getId()) != searchPay.getUserId().longValue()) {
			 throw new BaseException(CommonConstants.STATUS_ERROR_CODE, "payId错误");
		}
		if(searchPay.getPgPayStatus().intValue() == ShopOrderPay.PAY_STATUS_YES) {
			 throw new BaseException(CommonConstants.STATUS_ERROR_CODE, "订单已经支付");
		}
		//根据订单查询
		String orderIds = searchPay.getOrderSnS();
		//提交第三方支付的订单号
		String pgOrderSn = searchPay.getPgOrderSn();
		orderIds = orderIds.substring(1, orderIds.length() - 1).trim();
		String[] orderArray = orderIds.split("\\|\\|");
		//总金额
		long totalPrice = 0; 
		//总重量
		long totalFreight = 0;
		//总优惠
		long totalPromotion = 0;
		String responseMsg = "";
		if(payType.intValue() != ShopCommonConstant.SHOP_PAY_TYPE_WX && 
		   payType.intValue() != ShopCommonConstant.SHOP_PAY_TYPE_ALI &&
		   payType.intValue() != ShopCommonConstant.SHOP_PAY_TYPE_CCB) {
		   if(StringUtils.isEmpty(payPwd)) {
			   throw new BaseException(CommonConstants.STATUS_ERROR_CODE, "支付密码不能为空");
		   }
		   //验证支付密码是否正确
		   ApiRestResponse<Boolean> userResponse = userService.checkPayPwd(token, payPwd);
		   if(userResponse.getStatus() != CommonConstants.STATUS_OK_CODE) {
			   throw new BaseException(userResponse.getStatus(), userResponse.getMessage());
		    }	
		}
		for(String orderId : orderArray) {
			//查询订单信息
			ShopOrder shopOrder = shopOrderBiz.selectByPrimaryKey(orderId);
			if(shopOrder == null || shopOrder.getUserId().longValue() != Long.parseLong(jwtInfo.getId())) {
				throw new BaseException(CommonConstants.STATUS_ERROR_CODE, "订单id错误");
			}
			if(shopOrder.getOrderStatus().intValue() != ShopOrder.ORDER_STATUS_COMFIRM) {
				throw new BaseException(CommonConstants.STATUS_ERROR_CODE, "订单状态错误");
			}
			if(shopOrder.getPayStatus().intValue() != ShopOrder.PAY_STATUS_NO) {
				throw new BaseException(CommonConstants.STATUS_ERROR_CODE, "订单已经支付");
			}
			//查询订单产品列表
			List<ShopOrderItems> shopOrderItemsList = shopOrderItemsBiz.selectOrderItemsList(orderId);
			if(shopOrderItemsList == null) {
				throw new BaseException(CommonConstants.STATUS_ERROR_CODE, "订单明细错误");
			}
			shopOrder.setPayMethod(payMethod);
			shopOrder.setPayType(payType);
			shopOrder.setStageNum(stageNum);
			shopOrder.setStageNumId(stageNumId);
			shopOrderBiz.updateSelectiveById(shopOrder);
			//验证订单规格
			for(ShopOrderItems shopOrderItems : shopOrderItemsList) {
			    //检测specId、goodId是否有效
				ShopGoods shopGoods = shopGoodsBiz.selectByPrimaryKey(shopOrderItems.getGoodsId());
				goodsService.checkShoppingGoods(shopGoods);
				ShopGoodsSpec shopGoodsSpec = shopGoodsSpecBiz.selectById(shopOrderItems.getGoodsSpecId());
				goodsService.checkGoodsSpec(shopGoodsSpec);
				//检测库存是否足够
				if(shopGoods.getStockStatus() == -1) {
					throw new BaseException(CommonConstants.STATUS_ERROR_CODE, "库存不够");
				}
				if(shopGoodsSpec.getStockQuantity().intValue() < shopOrderItems.getProductNum().intValue() ) {
					throw new BaseException(CommonConstants.STATUS_ERROR_CODE, "库存不够");
				}
			}
		}		
		//修改支付方式
		ShopOrderPay modifyPay = new ShopOrderPay();
		modifyPay.setPgType(String.valueOf(payType));
		modifyPay.setPayId(payId);
		//微信支付（H5）
		if(payType.intValue() == ShopCommonConstant.SHOP_PAY_TYPE_WX) {
			if(StringUtils.isEmpty(openId)) {
				throw new BaseException(CommonConstants.STATUS_ERROR_CODE, "openId不能为空");
			}
			Integer payJoinId = busiConfiguration.getWeiXinPayJoinId();
			String nonceStr = Long.toString(System.currentTimeMillis());
			//防止订单id重复，重新生成第三方订单id
			pgOrderSn = MD5Utils.md5Hex(orderIds + nonceStr);
			modifyPay.setPgOrderSn(pgOrderSn);
			shopOrderPayBiz.updateSelectiveById(modifyPay);

			String callBackParams = Integer.toString(payJoinId);

			ApiRestResponse<String> response = weiXinService.unifiedOrderJsApi(payJoinId, pgOrderSn, searchPay.getPgPayAmount(), openId, callBackParams);
			if(response.getStatus() != CommonConstants.STATUS_OK_CODE) {
				throw new BaseException(response.getStatus(), response.getMessage());
			}	
			responseMsg = response.getData();
		}
		else if(payType.intValue() == ShopCommonConstant.SHOP_PAY_TYPE_ALI) {
			shopOrderPayBiz.updateSelectiveById(modifyPay);

		}
		else if(payType.intValue() == ShopCommonConstant.SHOP_PAY_TYPE_CCB) {
			Integer payJoinId = busiConfiguration.getCcbPayJoinId();
			String nonceStr = Long.toString(System.currentTimeMillis());
			//防止订单id重复，重新生成第三方订单id
			pgOrderSn = MD5Utils.md5Hex(orderIds + nonceStr);
			modifyPay.setPgOrderSn(pgOrderSn);
			shopOrderPayBiz.updateSelectiveById(modifyPay);

			String callBackParams = Integer.toString(payJoinId);
			ApiRestResponse<String> response = payService.threeStarPayInApp(payJoinId, pgOrderSn, searchPay.getPgPayAmount());
			if(response.getStatus() != CommonConstants.STATUS_OK_CODE) {
				throw new BaseException(response.getStatus(), response.getMessage());
			}	
			responseMsg = response.getData();
		}
		//内部支付
		else {
			shopOrderPayBiz.updateSelectiveById(modifyPay);

			ApiRestResponse<Integer> response = userAccountService.reduceBalance(payType, Long.parseLong(jwtInfo.getId()), jwtInfo.getUniqueName(), 
					String.valueOf(payId), ShopCommonConstant.USER_ACCOUNT_DETAIL_TYPE_PAY_GOODS, BigDecimal.valueOf(searchPay.getPgPayAmount()), null, null, null, "购买产品");	
			if(response.getStatus() != CommonConstants.STATUS_OK_CODE) {
				throw new BaseException(response.getStatus(), response.getMessage());
			}	
			if(response.getData().intValue() != 1) {
				throw new BaseException(CommonConstants.STATUS_ERROR_CODE, "支付失败");
			}
			//更新订单、订单产品、支付
			modifyPay.setPgPayStatus(ShopOrderPay.PAY_STATUS_YES);
			modifyPay.setPgPayTime(new Date());
			shopOrderPayBiz.updateSelectiveById(modifyPay);
			modifyOrderPaySuccess(searchPay.getOrderSnS(), payType);
		}
		return responseMsg;
	}
	
	/**
	 * 更新订单状态
	 * @param orderIds
	 */
	public void modifyOrderPaySuccess(String orderIds, Integer payType) {
		orderIds = orderIds.substring(1, orderIds.length() - 1).trim();
		String[] orderArray = orderIds.split("\\|\\|");
		for(String orderId : orderArray) {
			//查询订单信息
			ShopOrder shopOrder = shopOrderBiz.selectByPrimaryKey(orderId);
			//查询订单产品列表
			List<ShopOrderItems> shopOrderItemsList = shopOrderItemsBiz.selectOrderItemsList(orderId);
			if(shopOrderItemsList == null) {
				throw new BaseException(CommonConstants.STATUS_ERROR_CODE, "订单明细错误");
			}
			//更新状态
			//shopOrder.setOrderStatus(ShopOrder.ORDER_STATUS_COMFIRM);
			shopOrder.setPayType(payType);
			shopOrder.setOrderStatus(ShopOrder.ORDER_STATUS_PAY_OK);
			shopOrder.setPayStatus(ShopOrder.PAY_STATUS_YES);
			shopOrder.setPayTime(new Date());
			shopOrderBiz.updateSelectiveById(shopOrder);
			//验证订单规格
			for(ShopOrderItems shopOrderItems : shopOrderItemsList) {
			    //检测specId、goodId是否有效
				ShopGoods shopGoods = shopGoodsBiz.selectByPrimaryKey(shopOrderItems.getGoodsId());
				ShopGoodsSpec shopGoodsSpec = shopGoodsSpecBiz.selectById(shopOrderItems.getGoodsSpecId());
				//减少库存
				shopGoodsSpec.setStockQuantity(shopGoodsSpec.getStockQuantity() - shopOrderItems.getProductNum());
				shopGoodsSpecBiz.updateSelectiveById(shopGoodsSpec);
				
				shopGoods.setSoldNum(shopGoods.getSoldNum() + shopOrderItems.getProductNum());
				shopGoods.setShowSoldNum(shopGoods.getShowSoldNum() + shopOrderItems.getProductNum());
				
				shopGoodsBiz.updateSelectiveById(shopGoods);
			}
			
			//发送到消息队列
			rabbitSender.sendOrderPaySucceed(shopOrder);
		}		
	}

	@Override
	public void synOrderPayStatus(Integer joinAppId, String pgOrderSn, String transactionId, String nonceStr,
			String sign) throws Exception {
		//签名认证
		SortedMap<String, String> params = new TreeMap<String, String>();
		params.put("pgOrderSn", pgOrderSn);
		params.put("nonceStr", nonceStr);
		params.put("transactionId", transactionId);
		params.put("joinAppId", Integer.toString(joinAppId));
		String strSign = MD5SignUtils.createMD5Sign(params, "UTF-8");
		if(!StringUtils.equals(strSign, sign)) {
			throw new BaseException(CommonConstants.STATUS_ERROR_CODE, "签名失败");
		}
		//查询订单
		ShopOrderPay shopOrderPay = shopOrderPayBiz.selectByPgOrderSn(pgOrderSn);
		if(shopOrderPay == null) {
			throw new BaseException(CommonConstants.STATUS_ERROR_CODE, "pgOrderSn错误");
		}
		if(shopOrderPay.getPgPayStatus() == ShopOrderPay.PAY_STATUS_NO) {
			ShopOrderPay modifyPay = new ShopOrderPay();
			modifyPay.setPayId(shopOrderPay.getPayId());
			modifyPay.setPgPayStatus(ShopOrderPay.PAY_STATUS_YES);
			modifyPay.setPgPayTime(new Date());
			modifyPay.setPgTradeNo(transactionId);
			shopOrderPayBiz.updateSelectiveById(modifyPay);
			
			modifyOrderPaySuccess(shopOrderPay.getOrderSnS(), Integer.parseInt(shopOrderPay.getPgType()));
		}
		else {
			throw new BaseException(CommonConstants.STATUS_ERROR_CODE, "支付状态错误");
		}
	}
}
